package updown.service.updown;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import updown.data.ExecutorPoolUtil;
import updown.domain.TaskWrapper;
import updown.service.jar.UploadJarService;
import updown.service.task.ScheduleTaskService;
import updown.util.DateUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * <p>Title: updown.service.task </p>
 * <p>Description:updown: -  </p>
 *
 * @Author:jiangkaixin
 * @Date:1/5/2022
 * @Version: 1.0
 */
@Slf4j
@Service
public class DownUpScheduleService {

    public static final Map<String, ScheduledFuture> futureMap = new HashMap<>();
    public static final Map<String, TaskWrapper> taskMap = new HashMap<>();

    @Autowired
    private ScheduleTaskService scheduleTaskService;

    @Autowired
    private DownUpServiceWithRetry downUpService;

    @Autowired
    private UploadJarService uploadJarService;

    /**
     * 定时任务 丢到定时器
     *
     * @param taskWrapper
     */
    public void downUpSchedule(TaskWrapper taskWrapper) {
        log.info("定时任务丢入的 task:{}",taskWrapper);
        ScheduledFuture scheduledFuture = scheduleDownUpTask(taskWrapper);
        // 放入 futureMap，用于取消
        futureMap.put(taskWrapper.getTaskId(), scheduledFuture);
        taskMap.put(taskWrapper.getTaskId(), taskWrapper);
        // 保存  schedule 和 taskWrapper
        try {
            scheduleTaskService.saveToDB(taskWrapper);
        } catch (Exception e) {
            log.info("saveToDB error:{}", e);
            futureMap.get(taskWrapper.getTaskId()).cancel(false);
            taskMap.get(taskWrapper.getTaskId());
            log.info("取消任务，删除taskMap成功");
        }
    }

    /**
     * 取消定时任务
     *
     * @param taskId
     */
    public void cancelDownUpSchedule(String taskId) {
        TaskWrapper taskWrapper = taskMap.get(taskId);
        // 检查是否正在替换中
        if (DownUpServiceWithRetry.downDownMap.get(taskWrapper.getServiceName()) != null) {
            log.info("正在替换中无法取消");
            return;
        }
        ScheduledFuture scheduledFuture = futureMap.get(taskId);
        scheduledFuture.cancel(false);

        scheduleTaskService.cancel(taskWrapper);
    }

    public ScheduledFuture scheduleDownUpTask(TaskWrapper taskWrapper) {
        String scheduleTime = taskWrapper.getDownUpSchedule().getScheduleTime();
        Integer minutesLater = DateUtils.getMinutesBetweenNoError(DateUtils.getCurDateTime(), scheduleTime);
        log.info("丢入到定时器线程池，在多少分钟后启动:{}", minutesLater);

        ScheduledFuture<?> scheduleFuture = ExecutorPoolUtil.schedulePool.schedule(() -> {
            try {
                taskWrapper.setStartTime(DateUtils.getCurDateTime());
                // 1 根据传入的 file 地址，传送jar包到 对应的服务器
                if (!uploadJarService.sendJarToServerNew(taskWrapper)) {
                    log.info("scheduleDownUpTask 同步jar到servers 报错，停止停止回滚操作");
                }
                log.info("scheduleDownUpTask() 发送jar 完成");
                // 2 调用 downUp 执行重启任务
                if (!downUpService.executeDownUp(taskWrapper)) {
                    // 重启失败
                }
                // 3 执行成功的操作
                taskWrapper.endSuccess(Boolean.TRUE);
                scheduleTaskService.updateScheduleTask(taskWrapper);

                // 4. 删除两个map
                DownUpScheduleService.taskMap.remove(taskWrapper.getTaskId());
                DownUpScheduleService.futureMap.remove(taskWrapper.getTaskId());
            } catch (Exception e) {
                log.info("定时任务报错 error:{}",e);
            }

        }, minutesLater, TimeUnit.MINUTES);
        return scheduleFuture;
    }
}
